package global

import (
	"bytes"
	"cron_table_admin/config"
	"database/sql"
	"encoding/json"
	"fmt"
	"github.com/robfig/cron/v3"
	"gorm.io/gorm"
	"io/ioutil"
	"sync"

	"github.com/gin-gonic/gin"
	"github.com/go-redis/redis"
	"github.com/hibiken/asynq"
	oplogging "github.com/op/go-logging"
	"github.com/spf13/viper"
	"github.com/zheng-ji/goSnowFlake"
	"go.uber.org/zap"
)

var (
	GORM_DB           *gorm.DB
	REDIS_CONN        *redis.Client
	SERVER_CONFIG     config.Server
	VIPER_CONFIG      *viper.Viper
	OPLOGGER          *oplogging.Logger
	LOGGER            *zap.Logger
	MysqlDb           *sql.DB
	AsynqCient        *asynq.Client
	UniqId            *goSnowFlake.IdWorker
	CronTable         *cron.Cron
	CronMappingId     map[int64]cron.EntryID
	CronMappingIdLock sync.RWMutex
)

func init() {
	CronTable = cron.New()
	CronMappingId = make(map[int64]cron.EntryID)
	CronTable.Start()
}

func SetCronMappingId(id int64, entry cron.EntryID) {
	CronMappingIdLock.Lock()
	defer CronMappingIdLock.Unlock()
	CronMappingId[id] = entry
	return
}

func GetCronMappingId(id int64) cron.EntryID {
	CronMappingIdLock.RLocker()
	defer CronMappingIdLock.RUnlock()
	return CronMappingId[id]
}

func DelCronMappingId(id int64) {
	CronMappingIdLock.Lock()
	defer CronMappingIdLock.Unlock()
	delete(CronMappingId, id)
}

func LoggerWithContext(ctx *gin.Context) zap.Logger {
	newLogger := LOGGER
	if ctx != nil {
		RequestId := ctx.GetHeader("X-Request-ID")
		newLogger = newLogger.With(zap.String("RequestId", RequestId))
	}
	return *newLogger
}

func GetParameters(ctx *gin.Context) map[string]interface{} {
	var mapResult map[string]interface{}

	params2 := make(map[string]string)

	dataJson, err := ctx.GetRawData()
	if err != nil {
		fmt.Println(err.Error())
	}

	// 获取非 GET 的参数
	if ctx.Request.Method != "GET" {
		if env := VIPER_CONFIG.Get("system.is_decode"); env == true {
			err = json.Unmarshal(dataJson, &params2)
			if err != nil {
			}
			//params := utils.MyDESDecrypt(params2["sign"])
			//ctx.Request.Body = ioutil.NopCloser(bytes.NewBuffer(params))
		} else {
			// 直接获取 body 内容
			//dataJson, _ := ctx.GetRawData()
			// 取出来之后需要重新赋值回去，不然处理函数取不到值
			ctx.Request.Body = ioutil.NopCloser(bytes.NewBuffer(dataJson))

			_ = json.Unmarshal(dataJson, &mapResult)
		}
	}

	// 获取 Get 的参数
	Params := ctx.Request.URL.Query()
	if mapResult == nil {
		mapResult = make(map[string]interface{})
	}

	for k, v := range Params {
		value := v[0]
		_, ok := mapResult[k]
		// 如果post参数同名，以最终post 上传的 参数为准， 不进行覆盖
		if !ok {
			mapResult[k] = value
		}
	}
	ctx.Set("Param", mapResult)
	return mapResult
}
